/******************************************************************************* * Copyright (c) 2009, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Patrik Suzzi <psuzzi@gmail.com> - Bug 473973 * Friederike Schertel <friederike@schertel.org> - Bug 478336 ******************************************************************************/ package org.eclipse.ui.internal.statushandlers; import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; import java.util.Collection; import java.util.Iterator; import java.util.Map; import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.DialogTray; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.dialogs.TrayDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.internal.Workbench; import org.eclipse.ui.internal.WorkbenchMessages; import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.internal.progress.ProgressManagerUtil; import org.eclipse.ui.internal.progress.ProgressMessages; import org.eclipse.ui.progress.IProgressConstants; import org.eclipse.ui.statushandlers.StatusAdapter; import org.eclipse.ui.statushandlers.StatusManager; import org.eclipse.ui.views.IViewDescriptor; /** * Parent window actually does not use its Shell to build dialog on. The * window passes the shell to the InternalDialog, and it can do switching * modality and recreate the window silently. * * @since 3.4 */ public class InternalDialog extends TrayDialog { /** * The id of the goto action button */ static final int GOTO_ACTION_ID = IDialogConstants.CLIENT_ID + 1; static final String LOG_VIEW_ID = "org.eclipse.pde.runtime.LogView"; //$NON-NLS-1$ /** * Preference used to indicate whether the user should be prompted to * confirm the execution of the job's goto action */ static final String PREF_SKIP_GOTO_ACTION_PROMPT = "pref_skip_goto_action_prompt"; //$NON-NLS-1$ /** * This composite holds all components of the dialog. */ private Composite dialogArea; /** * This composite is initially scrolled to the 0 x 0 size. When more * than one status arrives, listArea is resized and a list is created on * it to present statuses to the user. */ private Composite listArea; /** * On this composite are presented additional elements for displaying * single status. Currently it is the second label that displays the * second most important message to the user. */ private Composite singleStatusDisplayArea; /** * This label is used to display the second most important message to * the user. It is placed on singleStatusDisplayArea. */ private Label singleStatusLabel; /** * A list from which the user selects statuses. The list is placed on * listArea. */ private TableViewer statusListViewer; /** * Composite on the left bottom corner. Allows for opening support tray * & Error Log. */ private Composite linkComposite; /** * This item is used to launch support tray */ private Link launchTrayLink; /** * This fields contains indicator if link to ErrorLog view should be * present. */ private Link showErrorLogLink; /** * Main dialog image holder. */ private Label titleImageLabel; /** * Message in the header. */ private Label mainMessageLabel; /** * Header area. */ private Composite titleArea; /** * In this support tray status support providers are displayed. */ private SupportTray supportTray; private DetailsAreaManager detailsManager; private Map dialogState; /** * @param dialogState * @param modal */ public InternalDialog(final Map dialogState, boolean modal) { super(ProgressManagerUtil.getDefaultParent()); this.dialogState = dialogState; supportTray = new SupportTray(dialogState, event -> { dialogState.put(IStatusDialogConstants.TRAY_OPENED, Boolean.FALSE); // close the tray closeTray(); // set focus back to shell getShell().setFocus(); }); detailsManager = new DetailsAreaManager(dialogState); setShellStyle(SWT.RESIZE | SWT.MAX | SWT.MIN | getShellStyle()); setBlockOnOpen(false); if (!modal) { setShellStyle(~SWT.APPLICATION_MODAL & getShellStyle()); } } @Override protected void buttonPressed(int id) { if (id == GOTO_ACTION_ID) { IAction gotoAction = getGotoAction(); if (gotoAction != null) { if (isPromptToClose()) { okPressed(); // close the dialog gotoAction.run(); // run the goto action } } } if (id == IDialogConstants.DETAILS_ID) { // was the details button pressed? dialogState.put(IStatusDialogConstants.DETAILS_OPENED, Boolean.valueOf( toggleDetailsArea())); } else { super.buttonPressed(id); } } @Override final protected void configureShell(Shell shell) { super.configureShell(shell); shell.setText(getString(IStatusDialogConstants.TITLE)); } /** * Status dialog button should be aligned SWT.END. */ @Override protected void setButtonLayoutData(Button button) { GridData data = new GridData(SWT.END, SWT.CENTER, false, false); int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); Point minSize = button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); data.widthHint = Math.max(widthHint, minSize.x); button.setLayoutData(data); } @Override protected Control createDialogArea(Composite parent) { createTitleArea(parent); createListArea(parent); dialogArea = parent; Dialog.applyDialogFont(dialogArea); return parent; } @Override protected boolean isResizable() { return true; } /** * Creates title area. * * @param parent * A composite on which the title area should be created. */ private void createTitleArea(Composite parent) { titleArea = new Composite(parent, SWT.NONE); titleArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.horizontalSpacing = 10; layout.marginLeft = 10; layout.marginTop = 10; layout.marginBottom = 0; titleArea.setLayout(layout); titleImageLabel = new Label(titleArea, SWT.NONE); titleImageLabel.setImage(getLabelProviderWrapper() .getImage(getCurrentStatusAdapter())); GridData layoutData = new GridData(); layoutData.verticalSpan = 2; layoutData.verticalAlignment = SWT.TOP; titleImageLabel.setLayoutData(layoutData); GridData messageData = new GridData(SWT.FILL, SWT.FILL, true, true); messageData.widthHint = convertWidthInCharsToPixels(50); mainMessageLabel = new Label(titleArea, SWT.WRAP); mainMessageLabel.setLayoutData(messageData); // main message set up early, to address bug 222391 mainMessageLabel.setText(getLabelProviderWrapper() .getMainMessage(getCurrentStatusAdapter())); if (!isMulti()) { singleStatusDisplayArea = createSingleStatusDisplayArea(titleArea); } } /** * Create an area which allows the user to view the status if only one * is created or to select one of reported statuses when there are many. * * @param parent * the parent composite on which all components should be * placed. */ private void createListArea(Composite parent) { listArea = new Composite(parent, SWT.NONE); GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); layoutData.heightHint = 0; layoutData.widthHint = 0; listArea.setLayoutData(layoutData); GridLayout layout = new GridLayout(); listArea.setLayout(layout); if (isMulti()) { fillListArea(listArea); } } /** * This function checks if the dialog is modal. * * @return true if the dialog is modal, false otherwise * */ public boolean isModal() { return ((getShellStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL); } /** * @return Returns the supportTray. */ public SupportTray getSupportTray() { return supportTray; } /** * @param supportTray * The supportTray to set. */ public void setSupportTray(SupportTray supportTray) { this.supportTray = supportTray; } @Override public int open() { boolean modalitySwitch = getBooleanValue(IStatusDialogConstants.MODALITY_SWITCH); int result = super.open(); if (modalitySwitch) { if (getBooleanValue(IStatusDialogConstants.DETAILS_OPENED)) { showDetailsArea(); } if (getBooleanValue(IStatusDialogConstants.TRAY_OPENED)) { openTray(); } } else { if (getBooleanValue(IStatusDialogConstants.ANIMATION)) { Rectangle shellPosition = getShell().getBounds(); ProgressManagerUtil.animateUp(shellPosition); } } return result; } @Override public void closeTray() throws IllegalStateException { if (getTray() != null) { super.closeTray(); } //preserve state during modality switch if (!getBooleanValue(IStatusDialogConstants.MODALITY_SWITCH)) { dialogState.put(IStatusDialogConstants.TRAY_OPENED, Boolean.FALSE); } if (launchTrayLink != null && !launchTrayLink.isDisposed()) { launchTrayLink.setEnabled(providesSupport() && !getBooleanValue(IStatusDialogConstants.TRAY_OPENED)); } } /** * Method which should be invoked when new errors become available for * display. */ void refresh() { if (dialogArea == null || dialogArea.isDisposed()) { return; } updateTitleArea(); updateListArea(); updateEnablements(); // adjust width if necessary Point currentSize = getShell().getSize(); Point desiredSize = getShell() .computeSize(SWT.DEFAULT, SWT.DEFAULT); if (currentSize.x < desiredSize.x) { getShell().setSize(desiredSize.x, currentSize.y); } else { getShell().layout(); } } void refreshDialogSize() { if (dialogArea == null || dialogArea.isDisposed()) { return; } Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); getShell().setSize(newSize); } /** * Show the details portion of the dialog if it is not already visible. * This method will only work when it is invoked after the control of * the dialog has been set. In other words, after the * <code>createContents</code> method has been invoked and has returned * the control for the content area of the dialog. Invoking the method * before the content area has been set or after the dialog has been * disposed will have no effect. */ private void showDetailsArea() { if (dialogArea != null && !dialogArea.isDisposed()) { if (detailsManager.isOpen()) { detailsManager.close(); detailsManager.createDetailsArea(dialogArea, getCurrentStatusAdapter()); dialogState.put(IStatusDialogConstants.DETAILS_OPENED, Boolean.TRUE); } else { toggleDetailsArea(); dialogState.put(IStatusDialogConstants.DETAILS_OPENED, Boolean.TRUE); } dialogArea.layout(); } } /** * Toggles the unfolding of the details area. This is triggered by the * user pressing the details button. * */ private boolean toggleDetailsArea() { boolean opened = false; Point windowSize = getShell().getSize(); if (detailsManager.isOpen()) { detailsManager.close(); getButton(IDialogConstants.DETAILS_ID).setText( IDialogConstants.SHOW_DETAILS_LABEL); opened = false; } else { detailsManager.createDetailsArea(dialogArea, getCurrentStatusAdapter()); getButton(IDialogConstants.DETAILS_ID).setText( IDialogConstants.HIDE_DETAILS_LABEL); opened = true; } GridData listAreaGridData = (GridData) listArea.getLayoutData(); // if there is only one status to display, // make sure that the list area is as small as possible if (!isMulti()) { listAreaGridData.heightHint = 0; } // allow listArea to grab space depending if details // are opened or not if (opened) { listAreaGridData.grabExcessVerticalSpace = false; } else { listAreaGridData.grabExcessVerticalSpace = true; } listArea.setLayoutData(listAreaGridData); Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); int diffY = newSize.y - windowSize.y; // increase the dialog height if details were opened and such // increase is necessary // decrease the dialog height if details were closed and empty space // appeared if ((opened && diffY > 0) || (!opened && diffY < 0)) { getShell().setSize( new Point(windowSize.x, windowSize.y + (diffY))); } dialogArea.layout(); return opened; } /** * This method should initialize the dialog bounds. */ @Override protected void initializeBounds() { super.initializeBounds(); refreshDialogSize(); boolean modalitySwitch = getBooleanValue(IStatusDialogConstants.MODALITY_SWITCH); if (modalitySwitch) { getShell().setBounds(getShellBounds()); } } @Override public Point getInitialLocation(Point initialSize) { return super.getInitialLocation(initialSize); } /** * The selection in the multiple job list has changed. Update widget * enablements, repopulate the list and show details. */ private void handleSelectionChange() { StatusAdapter newSelection = getSingleSelection(); if (newSelection != null) { dialogState.put(IStatusDialogConstants.CURRENT_STATUS_ADAPTER, newSelection); showDetailsArea(); refresh(); } } /** * This method creates display area for {@link StatusAdapter}s when more * is available. * * @param parent * A parent composite on which all components should be * placed. */ private void fillListArea(Composite parent) { // it is necessary to make list parent composite taller GridData listAreaGD = (GridData) parent.getLayoutData(); listAreaGD.grabExcessHorizontalSpace = true; if (!detailsManager.isOpen()) { listAreaGD.grabExcessVerticalSpace = true; } listAreaGD.heightHint = SWT.DEFAULT; // create list viewer statusListViewer = new TableViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); statusListViewer.setComparator(getLabelProviderWrapper()); Control control = statusListViewer.getControl(); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = convertHeightInCharsToPixels(5); control.setLayoutData(data); initContentProvider(); initLabelProvider(); statusListViewer.addPostSelectionChangedListener(event -> { handleSelectionChange(); if ((getTray() == null) && getBooleanValue(IStatusDialogConstants.TRAY_OPENED) && providesSupport()) { silentTrayOpen(); return; } if ((getTray() != null) && !providesSupport()) { silentTrayClose(); return; } supportTray.selectionChanged(event); }); Dialog.applyDialogFont(parent); } /** * closes the tray without changing any flag */ private void silentTrayClose() { super.closeTray(); } /** opens the tray without changing any flag */ private void silentTrayOpen() { if (getTray() == null) super.openTray(supportTray); } /** * This methods switches StatusAdapters presentation depending if there * is one status or more. */ private void updateListArea() { // take care about list area if there is more than one status if (isMulti()) { if (singleStatusDisplayArea != null) { singleStatusDisplayArea.dispose(); } if (statusListViewer == null || statusListViewer.getControl().isDisposed()) { fillListArea(listArea); listArea.layout(); listArea.getParent().layout(); getShell().setSize( getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT)); } refreshStatusListArea(); } } /** * Updated title area. Adjust title, title message and title image * according to selected {@link StatusAdapter}. */ private void updateTitleArea() { Image image = getLabelProviderWrapper().getImage( getCurrentStatusAdapter()); titleImageLabel.setImage(image); if (getCurrentStatusAdapter() != null) { mainMessageLabel.setText(getLabelProviderWrapper() .getMainMessage(getCurrentStatusAdapter())); } if (singleStatusDisplayArea != null) { if (isMulti()) { singleStatusDisplayArea.dispose(); } else { refreshSingleStatusArea(); } } titleArea.layout(); } /** * This method creates button bar that is available on the bottom of the * dialog. */ @Override protected Control createButtonBar(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); composite.setLayout(layout); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); linkComposite = createLinkComposite(composite); // Add the buttons to the button bar. createButtonsForButtonBar(composite); composite.layout(); return composite; } /** * This method creates buttons that are placed on button bar. */ @Override protected void createButtonsForButtonBar(Composite parent) { IAction gotoAction = getGotoAction(); String text = null; if (gotoAction != null) { text = gotoAction.getText(); } Button button = createButton(parent, GOTO_ACTION_ID, text == null ? "" : text, //$NON-NLS-1$ false); if (text == null) hideButton(button, true); createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); createButton(parent, IDialogConstants.DETAILS_ID, IDialogConstants.SHOW_DETAILS_LABEL, false); } /** * This method creates additional display area for {@link StatusAdapter} * when only one is available. * * It creates one label on a composite currently for secondary message. * * @param parent * A parent composite on which all components should be * placed. * @return composite the composite on which are all components for * displaying status when only one is available. */ private Composite createSingleStatusDisplayArea(Composite parent) { // secondary message is displayed on separate composite with no // margins Composite singleStatusParent = new Composite(parent, SWT.NONE); GridLayout gridLayout = new GridLayout(); gridLayout.marginWidth = 0; singleStatusParent.setLayout(gridLayout); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false); singleStatusParent.setLayoutData(gd); // label that wraps singleStatusLabel = new Label(singleStatusParent, SWT.WRAP); GridData labelLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true); labelLayoutData.widthHint = convertWidthInCharsToPixels(50); singleStatusLabel.setLayoutData(labelLayoutData); // main message set up early, to address bug 222391 singleStatusLabel.setText(getLabelProviderWrapper() .getColumnText(getCurrentStatusAdapter(), 0)); singleStatusLabel.addMouseListener(new MouseListener() { @Override public void mouseDoubleClick(MouseEvent e) { } @Override public void mouseDown(MouseEvent e) { showDetailsArea(); } @Override public void mouseUp(MouseEvent e) { } }); return singleStatusParent; } /** * This method closes the dialog. */ @Override public boolean close() { boolean modalitySwitch = getBooleanValue(IStatusDialogConstants.MODALITY_SWITCH); if (detailsManager.isOpen()) { dialogState.put(IStatusDialogConstants.DETAILS_OPENED, Boolean.TRUE); toggleDetailsArea(); } if (getBooleanValue(IStatusDialogConstants.TRAY_OPENED)) { closeTray(); if (modalitySwitch) { dialogState.put(IStatusDialogConstants.DETAILS_OPENED, Boolean.TRUE); } } dialogState.put(IStatusDialogConstants.SHELL_BOUNDS, getShell().getBounds()); statusListViewer = null; boolean result = super.close(); if (!modalitySwitch && getBooleanValue(IStatusDialogConstants.ANIMATION)) { ProgressManagerUtil.animateDown(getShellBounds()); } return result; } /** * Hide the button if hide is <code>true</code>. * * @param button * @param hide */ private void hideButton(Button button, boolean hide) { ((GridData) button.getLayoutData()).exclude = hide; button.setVisible(!hide); button.setEnabled(!hide); } /** * Update the button enablements */ private void updateEnablements() { Button details = getButton(IDialogConstants.DETAILS_ID); if (details != null) { details.setEnabled(true); } Button gotoButton = getButton(GOTO_ACTION_ID); if (gotoButton != null) { IAction gotoAction = getGotoAction(); boolean hasValidGotoAction = (gotoAction != null) && (gotoAction.getText() != null); if (hasValidGotoAction) { hideButton(gotoButton, false); gotoButton.setText(gotoAction.getText()); ((GridData) gotoButton.getLayoutData()).widthHint = gotoButton .computeSize(SWT.DEFAULT, SWT.DEFAULT).x; gotoButton.getParent().layout(); } else hideButton(gotoButton, true); } // and tray enablement button if (providesSupport() && !getBooleanValue(IStatusDialogConstants.HIDE_SUPPORT_BUTTON)) { if (launchTrayLink == null || launchTrayLink.isDisposed()) { launchTrayLink = createGetSupportLink(); } launchTrayLink .setEnabled(!getBooleanValue(IStatusDialogConstants.TRAY_OPENED)); } else { if (launchTrayLink != null && !launchTrayLink.isDisposed()) { launchTrayLink.dispose(); launchTrayLink = null; } } IViewDescriptor descriptor = shouldDisplayLinkToErrorLog(); if (descriptor != null) { if (showErrorLogLink == null || showErrorLogLink.isDisposed()) { showErrorLogLink = createShowErrorLogLink(); } } else { if (showErrorLogLink != null && !showErrorLogLink.isDisposed()) { showErrorLogLink.dispose(); } } linkComposite.getParent().layout(); } private IViewDescriptor shouldDisplayLinkToErrorLog() { /* no support for error log */ if (!getBooleanValue(IStatusDialogConstants.ERRORLOG_LINK)) { return null; } /* check handling hint and display link if it is expected */ boolean shouldDisplay = false; Iterator it = ((Collection) dialogState .get(IStatusDialogConstants.STATUS_ADAPTERS)).iterator(); while (it.hasNext()) { StatusAdapter adapter = (StatusAdapter) it.next(); Integer hint = (Integer) adapter.getProperty(WorkbenchStatusDialogManagerImpl.HINT); if (hint != null && ((hint.intValue() & StatusManager.LOG) != 0)) { shouldDisplay |= true; break; } } if (!shouldDisplay) { return null; } /* view description */ return Workbench.getInstance().getViewRegistry().find(LOG_VIEW_ID); } /** * Opens the dialog tray (support area at the right side of the dialog) */ @Override public void openTray(DialogTray tray) throws IllegalStateException, UnsupportedOperationException { if (launchTrayLink != null && !launchTrayLink.isDisposed()) { launchTrayLink.setEnabled(false); } if (providesSupport()) { super.openTray(tray); } dialogState.put(IStatusDialogConstants.TRAY_OPENED, Boolean.TRUE); } /** * Refreshes the single status area. Is called only when there is one * and only one error. */ private void refreshSingleStatusArea() { String description = getLabelProviderWrapper() .getColumnText(getCurrentStatusAdapter(), 0); if (description.equals(singleStatusLabel.getText())) singleStatusLabel.setText(" "); //$NON-NLS-1$ singleStatusLabel.setText(description); singleStatusDisplayArea.layout(); getShell().setText(getString(IStatusDialogConstants.TITLE)); } /** * Refresh the contents of the viewer. */ private void refreshStatusListArea() { if (statusListViewer != null && !statusListViewer.getControl().isDisposed()) { statusListViewer.refresh(); if (statusListViewer.getTable().getItemCount() > 1) { getShell() .setText( WorkbenchMessages.WorkbenchStatusDialog_MultipleProblemsHaveOccured); } else { getShell().setText( getString(IStatusDialogConstants.TITLE)); } } } /** * Sets the content provider for the viewer. */ private void initContentProvider() { IContentProvider provider = new IStructuredContentProvider() { @Override public void dispose() { // Nothing of interest here } @Override public Object[] getElements(Object inputElement) { return ((Collection) dialogState .get(IStatusDialogConstants.STATUS_ADAPTERS)).toArray(); } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (newInput != null) { refreshStatusListArea(); } } }; statusListViewer.setContentProvider(provider); statusListViewer.setInput(this); statusListViewer.setSelection(new StructuredSelection( getCurrentStatusAdapter())); } /** * Creates a new control that provides access to support providers. * <p> * The <code>WorkbenchStatusDialog</code> implementation of this method * creates the control, registers it for selection events including * selection, Note that the parent's layout is assumed to be a * <code>GridLayout</code> and the number of columns in this layout is * incremented. Subclasses may override. * </p> * * @param parent * A parent composite on which all components should be * placed. * @return the report control */ private Composite createLinkComposite(Composite parent) { Composite linkArea = new Composite(parent, SWT.NONE) { // the composite should be as small as possible when there is no // additional controls on it @Override public Point computeSize(int wHint, int hHint, boolean changed) { Point newSize = super.computeSize(wHint, hHint, changed); if (getChildren().length == 0) { newSize.x = 0; newSize.y = 0; } return newSize; } }; GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.verticalSpacing = 0; linkArea.setLayout(layout); ((GridLayout) parent.getLayout()).numColumns++; GridData layoutData = new GridData(SWT.BEGINNING, SWT.CENTER, true, false); linkArea.setLayoutData(layoutData); return linkArea; } /** * Creates a button with a report image. This is only used if there is * an image available. */ private Link createGetSupportLink() { // no support if (!providesSupport() || getBooleanValue(IStatusDialogConstants.HIDE_SUPPORT_BUTTON)) { return null; } Link link = new Link(linkComposite, SWT.NONE); link .setText(WorkbenchMessages.WorkbenchStatusDialog_SupportHyperlink); link .setToolTipText(WorkbenchMessages.WorkbenchStatusDialog_SupportTooltip); link.addSelectionListener(widgetSelectedAdapter(e -> openTray())); Dialog.applyDialogFont(link); return link; } private Link createShowErrorLogLink() { Link link = new Link(linkComposite, SWT.NONE); link.addSelectionListener(widgetSelectedAdapter(e -> { try { Workbench.getInstance().getActiveWorkbenchWindow().getActivePage().showView(LOG_VIEW_ID); } catch (CoreException ce) { StatusManager.getManager().handle(ce, WorkbenchPlugin.PI_WORKBENCH); } })); link.setText(WorkbenchMessages.ErrorLogUtil_ShowErrorLogHyperlink); link .setToolTipText(WorkbenchMessages.ErrorLogUtil_ShowErrorLogTooltip); Dialog.applyDialogFont(link); return link; } /** * Sets initial label provider. */ private void initLabelProvider() { statusListViewer.setLabelProvider(getLabelProviderWrapper()); } /** * Returns {@link IAction} associated with selected StatusAdapter. * * @return {@link IAction} that is set as {@link StatusAdapter} property * with Job.class key. */ private IAction getGotoAction() { Object property = null; Job job = Adapters.adapt(getCurrentStatusAdapter(), Job.class); if (job != null) { property = job.getProperty(IProgressConstants.ACTION_PROPERTY); } if (property instanceof IAction) { return (IAction) property; } return null; } /** * Get the single selection. Return null if the selection is not just * one element. * * @return StatusAdapter or <code>null</code>. */ private StatusAdapter getSingleSelection() { IStructuredSelection selection = statusListViewer.getStructuredSelection(); if (selection.size() == 1) { return (StatusAdapter) selection.getFirstElement(); } return null; } /* * Prompt to inform the user that the dialog will close and the errors * cleared. */ private boolean isPromptToClose() { IPreferenceStore store = WorkbenchPlugin.getDefault() .getPreferenceStore(); if (!store.contains(PREF_SKIP_GOTO_ACTION_PROMPT) || !store.getString(PREF_SKIP_GOTO_ACTION_PROMPT).equals( MessageDialogWithToggle.ALWAYS)) { MessageDialogWithToggle dialog = MessageDialogWithToggle.open( MessageDialog.CONFIRM, getShell(), ProgressMessages.JobErrorDialog_CloseDialogTitle, ProgressMessages.JobErrorDialog_CloseDialogMessage, ProgressMessages.JobErrorDialog_DoNotShowAgainMessage, false, store, PREF_SKIP_GOTO_ACTION_PROMPT, SWT.SHEET); return dialog.getReturnCode() == Window.OK; } return true; } public void openTray() { openTray(supportTray); } public boolean providesSupport() { return supportTray.providesSupport(getCurrentStatusAdapter()) != null; } private String getString(Object key) { return (String) dialogState.get(key); } private StatusAdapter getCurrentStatusAdapter() { return (StatusAdapter) dialogState .get(IStatusDialogConstants.CURRENT_STATUS_ADAPTER); } private boolean getBooleanValue(Object key) { Boolean b = (Boolean) dialogState.get(key); if (b == null) { return false; } return b.booleanValue(); } private Rectangle getShellBounds() { return (Rectangle) dialogState.get(IStatusDialogConstants.SHELL_BOUNDS); } private LabelProviderWrapper getLabelProviderWrapper() { return (LabelProviderWrapper) dialogState .get(IStatusDialogConstants.LABEL_PROVIDER); } private boolean isMulti() { return ((Collection) dialogState .get(IStatusDialogConstants.STATUS_ADAPTERS)).size() > 1; } }